const path = require('path')
const { htmlEncodeByRegExp, errorLog } = require('../util.js')
const jsdoc2md = require('jsdoc-to-markdown')

class RenderMd {
  // 文件头部的title
  static titleMdStr = ''

  /**
   * 输出md文件信息 参考：jsdoc2md.getTemplateData / getTemplateDataSync
   * @param {*} fromPath js文件路径
   * @param {*} jsdoc jsdoc配置项
   * @return {Promise}
   * @memberof RenderMd
   * @example RenderMd.render('path/file.vue',{configure:''});
   */
  static render(fromPath, jsdoc = null) {
    return new Promise((resolve) => {
      let params = RenderMd.getJsdocParam(jsdoc, { files: fromPath })
      jsdoc2md.getTemplateData(params).then((jsdocDataList) => {
        if (jsdocDataList && jsdocDataList.length > 0) {
          RenderMd.titleMdStr = ''
          let mdItemListArr = RenderMd.getMdItemList(jsdocDataList)
          let mdFileData = RenderMd.getMdFileData(mdItemListArr)
          resolve(mdFileData)
        } else {
          errorLog('该文件没有jsdoc注释，获取数据为空应主动忽略，现不处理该文件',fromPath)
          resolve(null)
        }
      })
    })
  }

  /**
   * 获取jsdoc配置项
   * @param {*} obj
   * @return {*}
   * @memberof RenderMd
   */
  static getJsdocParam(jsdoc, obj) {
    jsdoc && (obj = Object.assign({}, obj, jsdoc))
    return obj
  }

  /**
   * 演示例子文本
   * @static
   * @param {array} examples
   * @return {*}
   * @memberof RenderMd
   */
  static getDemo(examples) {
    let str = ''
    if (examples && examples.length) {
      let codeFlagStr = '```'

      let codeType = 'js'

      let flagStr = ':::'

      // md 代码类型
      let demoNameStr = 'details'

      let des = '查看例子代码'

      let code = examples.join('\n')

      // :::details Alert 组件提供四种主题，由`type`属性指定，默认值为`info`。
      let headStr = `${flagStr}${demoNameStr} ${des}\n`

      // ```js
      // ...
      // ```
      let codeStr = `${codeFlagStr}${codeType}\n${code}\n${codeFlagStr}\n`

      // :::
      let footStr = `${flagStr}\n`

      str = headStr + codeStr + footStr
    }
    return str
  }

  /**
   * 获取函数信息列表
   * @param {*} listData
   * @return {*}
   * @memberof RenderMd
   */
  static getMdItemList(listData) {
    // 列表
    let mdItemListArr = []

    for (const item of listData) {
      // 函数名
      let name = item['name']
      // 描述
      let des = item['description']
      // 属于
      // let memberof = item['memberof']
      // 返回
      let returns = item['returns']
      // 参数
      let params = item['params']
      // 文件源信息
      let meta = item['meta']

      let examples = item['examples']

      // 文件头部title
      if (!RenderMd.titleMdStr) {
        RenderMd.titleMdStr = RenderMd.getTitleMd(meta)
      }

      let mdItemArr = RenderMd.getMdItem(name, des, params, returns, examples)
      mdItemListArr.push(mdItemArr)
    }

    return mdItemListArr
  }

  /**
   * 获取md文本数据
   * @param {*} mdItemListArr
   * @return {*}
   * @memberof RenderMd
   */
  static getMdFileData(mdItemListArr) {
    let mdFileData = ''
    // 每个接口函数信息栏的分割符
    let itemSplitSymbol = `\n\n---\n\n`
    // 接口函数信息栏每条信息的分隔符
    let itemTextSplitSymbol = '\n'
    // 拼接全部
    for (const mdItemArr of mdItemListArr) {
      let itemText = mdItemArr.join(itemTextSplitSymbol)
      mdFileData += itemText + itemSplitSymbol
    }

    // 添加title
    if (mdFileData) {
      mdFileData = RenderMd.titleMdStr + itemTextSplitSymbol + mdFileData + ''
    }

    return mdFileData
  }

  /**
   * 获取单个函数的信息
   * @param {*} name
   * @param {*} des
   * @param {*} params
   * @param {*} returns
   * @param {*} examples
   * @return {*}
   * @memberof RenderMd
   */
  static getMdItem(name, des, params, returns, examples) {
    let mdItemArr = []

    // 名字
    let nameStr = RenderMd.getNameMd(name)
    if (nameStr) {
      mdItemArr.push(nameStr)
    }

    // 详情
    let desStr = RenderMd.getDesMd(des)
    if (desStr) {
      mdItemArr.push(desStr)
    }

    // 参数
    let paramsStr = RenderMd.getParamsMd(params)
    if (paramsStr) {
      mdItemArr.push(paramsStr)
    }

    // 返回
    let returnsStr = RenderMd.getReturnsMd(returns)
    if (returnsStr) {
      mdItemArr.push(returnsStr)
    }

    // 例子
    let demoStr = RenderMd.getDemo(examples)
    if (demoStr) {
      mdItemArr.push(demoStr)
    }

    return mdItemArr
  }

  /**
   * 名字
   * @param {*} name
   * @return {*}
   * @memberof RenderMd
   */
  static getNameMd(name) {
    if (name) {
      if (name.indexOf('exports.') !== -1) {
        name = name.replace('exports.', '')
      }
      return `### ${name}`
    }
    return ''
  }

  /**
   * 详情
   * @param {*} des
   * @return {*}
   * @memberof RenderMd
   */
  static getDesMd(des) {
    if (des) {
      return `- 详情： ${des}`
    }
    return ''
  }

  /**
   * 返回参数
   * @param {*} returns
   * @return {*}
   * @memberof RenderMd
   */
  static getReturnsMd(returns) {
    if (!returns) {
      return null
    }
    let str = ''
    // [{"type":{"names":["array","undefined"]},"description":"返回列表"}]
    for (const item of returns) {
      let type = item['type']
      // 描述
      let description = item['description']
      let nameArr = []
      if (type) {
        // 类型字符
        let names = type['names']
        for (const name of names) {
          nameArr.push(`<code>${htmlEncodeByRegExp(name)}</code>`)
        }
        let typeStr = nameArr.join('|')

        let descriptionStr = ''
        if (description) {
          descriptionStr = `- ${description}`
        }

        str = `\n- 返回：${typeStr}${descriptionStr}`
        return str
      }
    }
    return str
  }

  /**
   * 生成头部title
   * @param {*} meta
   * @return {*}
   * @memberof RenderMd
   */
  static getTitleMd(meta) {
    let title = ''
    if (meta) {
      // 文件名
      let filename = meta['filename']
      if (filename) {
        let obj = path.parse(filename)
        let name = obj['name']
        title = `---\ntitle: ${name}\n---\n`
        return title
      }
    }
    return title
  }

  /**
   * 参数栅格列表
   * @param {*} params
   * @return {*}
   * @memberof RenderMd
   */
  static getParamsMd(params) {
    if (params && params.length) {
      let headDes = `\n| 参数 | 类型 | 默认值 | 描述 |`
      let tabelHead = `| --- | --- | --- | --- |`
      let tabelItemArr = [headDes, tabelHead]
      for (const param of params) {
        let name = param['name']
        let type = param['type']

        // 默认值
        let defaultvalue = param['defaultvalue']
        let defaultvalueStr = ' '

        // 参数名
        let nameStr = name
        if (defaultvalue) {
          nameStr = `[${name}]`
          defaultvalueStr = defaultvalue
          defaultvalueStr = `<code>${htmlEncodeByRegExp(defaultvalueStr)}</code>`
        }

        // 参数类型
        let paramTypeStr = ' '
        if (type) {
          let names = type['names']
          paramTypeStr = `<code>${htmlEncodeByRegExp(names)}</code>`
        }

        // 参数描述
        let description = param['description']
        let descriptionStr = ' '
        if (description) {
          descriptionStr = description
        }
        let item = `| ${nameStr} | ${paramTypeStr} | ${defaultvalueStr} | ${descriptionStr} |`
        tabelItemArr.push(item)
      }
      let paramsMdStr = tabelItemArr.join('\n')
      return paramsMdStr
    }
    return ''
  }
}

module.exports = RenderMd
